
import { defineComponent, h, render } from 'vue'
import { Spin } from 'ant-design-vue'

const Loading = defineComponent({
    props: ['spinning', 'tip', 'size'],
    setup (props) {
        return () => {
            if (props.spinning === false) return null
            return h(
                'div',
                {
                    style: {
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        right: 0,
                        bottom: 0,
                        zIndex: 99999,
                        backgroundColor: 'rgba(255, 255, 255, 0.5)',
                        display: 'flex',
                        justifyContent: 'center',
                        alignItems: 'center'
                    }
                },
                h(Spin, {
                    spinning: true,
                    tip: props.tip || '加载中...',
                    size: props.size || 'small'
                })
            )
        }
    }
})

// 函数式指令
function createLoadingElement (el, binding) {
    // 获取原始样式
    const originalPosition = window.getComputedStyle(el).position
    const originalOverflow = window.getComputedStyle(el).overflow

    el._originalPosition = originalPosition
    el._originalOverflow = originalOverflow

    if (originalPosition === 'static') {
        el.style.position = 'relative'
    }

    let spinning = true
    let tip = '加载中...'
    let size = 'small'

    if (typeof binding.value === 'string') {
        tip = binding.value
    } else if (typeof binding.value === 'object') {
        spinning = binding.value.spinning ?? true
        tip = binding.value.tip ?? '加载中...'
        size = binding.value.size ?? 'small'
    } else if (typeof binding.value === 'boolean') {
        spinning = binding.value
    }

    const container = document.createElement('div')
    const instance = h(Loading, { spinning, tip, size })
    render(instance, container)

    el._loadingContainer = container
    el.appendChild(container)

    if (spinning) {
        el.style.overflow = 'hidden'
    } else {
        el.style.overflow = originalOverflow
    }
}

function updateLoadingElement (el, binding) {
    const container = el._loadingContainer
    if (!container) return

    let spinning = true
    let tip = '加载中...'
    let size = 'small'

    if (typeof binding.value === 'string') {
        tip = binding.value
        spinning = true
    } else if (typeof binding.value === 'object') {
        spinning = binding.value.spinning ?? true
        tip = binding.value.tip ?? '加载中...'
        size = binding.value.size ?? 'small'
    } else if (typeof binding.value === 'boolean') {
        spinning = binding.value
    }

    const instance = h(Loading, { spinning, tip, size })
    render(instance, container)

    if (spinning) {
        el.style.overflow = 'hidden'
    } else if (el._originalOverflow) {
        el.style.overflow = el._originalOverflow
    }
}

function destroyLoadingElement (el) {
    if (el._loadingContainer) {
        el.removeChild(el._loadingContainer)
        delete el._loadingContainer
    }

    if (el._originalPosition) {
        el.style.position = el._originalPosition
        delete el._originalPosition
    }

    if (el._originalOverflow) {
        el.style.overflow = el._originalOverflow
        delete el._originalOverflow
    }
}

export default {
    mounted (el, binding) {
        createLoadingElement(el, binding)
    },
    updated (el, binding) {
        updateLoadingElement(el, binding)
    },
    beforeUnmount (el) {
        destroyLoadingElement(el)
    }
}